/*
 * @Author: Jiraiya
 * @Date: 2020-05-04 23:08:19
 * @LastEditors: Jiraiya
 * @LastEditTime: 2020-05-07 15:37:25
 * @Description: 
 */
'use strict';

const mysql = require('mysql');
const {logger} = bee;
const TransactionConnection = require('./TransactionConnection');



module.exports = function mysqlFactory(config){
    const pool = mysql.createPool(config);
    let singleton = null;

    class MysqlClient{
        
        /**
         * @description: 获取单例静态方式
         * @param {type} 
         * @return: 
         */
        static getSingle(){
            if(! singleton){
                singleton = new MysqlClient();
                return singleton;
            }
        }

        /**
         * @description: 断开数据库连接
         * @param {type} 
         * @return: 
         */
        close(){
            return new Promise( function(resolve, reject){
                pool.end(err => {
                    if(err){
                        logger.error('断开数据库连接失败');
                        return reject(err);
                    }
                    resolve();
                })
            })
        }


        /**
         * @description: 获取事务操作连接
         * @param {type} 
         * @return: 
         */
        getConnection(){
            return new Promise( function(resolve, reject){
                //当前配置的是 连接池 模式, 直接从池子中获取
                pool.getConnection( function(err, connection){
                    if( err ){
                        logger.error(`从MySQL连接池中获取connection失败: ${err}`);
                        return reject(err);
                    }
                    let conWrap = new TransactionConnection(connection);
                    resolve( conWrap );
                });
            });
        }


        /**
         * @description: query
         * @param {type} 
         * @return: 
         */
        query(sql, values){
            return new Promise( (resolve, reject) => {
                let finalSQL = sql;
                if( arguments.length === 2 ){
                    finalSQL = mysql.format(sql, values);
                }
                logger.info(`执行MySQL的SQL语句: ${finalSQL}`);
                pool.query(finalSQL, function(err, results, fields){
                    if( err ){
                        return reject(err);
                    }
                    resolve({
                        results : results,
                        fields : fields
                    });
                });
            });
        }

        /**
         * @description: 格式化字符串
         * @param {type} 
         * @return: 
         */
        format(sql, values){
            return mysql.format(sql, values);
        }

        /**
         * @description: 插入数据
         * @param {type} 
         * @return: 
         */
        async insert(table, rows){
            if (!Array.isArray(rows)) {
                rows = [rows];
            }

            const fields = Object.keys(rows[0]), len = rows.length;
            const template = `(${new Array(fields.length).fill('?').join(', ')})`;
            const sql = rows.reduce((str, obj, idx) => {
                const currentVal = fields.map(key => obj[key]);
                if(idx >= len - 1) return `${str} ${this.format(template, currentVal)}`
                return `${str} ${this.format(template, currentVal)}, `
            }, `INSERT INTO ${table} (${fields.join(', ')}) VALUES`)

            let out = await this.query(sql);
            return out.results;
        }     

        
    }

    return MysqlClient;
}